02 初步认识:Kubernetes 基础概念

好了,总算开始进入正题,抛弃掉死板的说教模式,我们以一个虚构的新成立的项目组为例开始我们的 Kubernetes 探索。(以下统一将 Kubernetes 简写为 K8S) 项目组目前就只有一个成员,我们称他为小张。项目组刚成立的时候,小张也没想好,具体要做什么,但肯定要对外提供服务的,所以先向公司申请了一台服务器。

Node

这台服务器可以用来做什么呢?跑服务,跑数据库,跑测试之类的都可以,我们将它所做的事情统称为工作(work) 那么,它便是工作节点 (worker Node) 对应于 K8S 中,这就是我们首先要认识的 Node 。

Node 可以是一台物理机,也可以是虚拟机,对于我们此处的项目来讲,这台服务器便是 K8S 中的 Node 。

Node 状态

当我们拿到这台服务器后,首先我们登录服务器查看下服务器的基本配置和信息。其实对于一个新加入 K8S 集群的 Node 也是一样,需要先检查它的状态,并将状态上报至集群的 master 。我们来看看服务器有哪些信息是我们所关心的。

地址

首先,我们所关心的是我们服务器的 IP 地址,包括内网 IP 和外网 IP。对应于 K8S 集群的话这个概念是类似的,内部 IP 可在 K8S 集群内访问,外部 IP 可在集群外访问。

其次,我们也会关心一下我们的主机名,比如在服务器上执行 hostname 命令,便可得到主机名。K8S 集群中,每个 Node 的主机名也会被记录下来。当然,我们可以通过给 Kubelet 传递一个 --hostname-override 的参数来覆盖默认的主机名。 (Kubelet 是什么,我们后面会解释)

信息

再之后,我们需要看下服务器的基本信息,比如看看系统版本信息, cat /etc/issue 或者 cat /etc/os-release 等方法均可查看。对于 K8S 集群会将每个 Node 的这些基础信息都记录下来。

容量

我们通常也都会关注下,我们有几个核心的 CPU ,可通过 cat /proc/cpuinfo 查看,有多大的内存 通过 cat /proc/meminfofree 等查看。对于 K8S 集群,会默认统计这些信息,并计算在此 Node 上可调度的 Pod 数量。(Pod 后面做解释)

条件

对于我们拿到的服务器,我们关心上述的一些基本信息,并根据这些信息进行判断,这台机器是否能满足我们的需要。对 K8S 集群也同样,当判断上述信息均满足要求时候,便将集群内记录的该 Node 信息标记为 ReadyReady = True),这样我们的服务器便正式的完成交付。我们来看下其他的部分。

Deployment 和 Pod

现在小张拿到的服务器已经是可用状态,虽然此时尚不知要具体做什么,但姑且先部署一个主页来宣布下项目组的成立。

我们来看下一般情况下的做法,先写一个静态页面,比如叫 index.html 然后在服务器上启动一个 Nginx 或者其他任何 Web 服务器,来提供对 index.html 的访问。

Nginx 的安装及配置可参考 Nginx 的官方文档。最简单的配置大概类似下面这样(仅保留关键部分):

location / {
    root   /www;
    index  index.html;
}

对于 K8S 而言,我们想要的,能提供对 index.html 访问的服务便可理解为 Deployment 的概念,表明一种我们预期的目标状态。

而对于 Nginx 和 index.html 这个组合可以理解为其中的 Pod 概念,作为最小的调度单元。

Container Runtime

虽然此刻部署的内容只有官网,但是为了避免单点故障,于是小张又申请了两台服务器(虽然看起来可能是浪费了点),现在要对原有的服务进行扩容,其实在新的服务器上我们所做的事情也还保持原样,部署 Nginx,提供对 index.html 的访问,甚至配置文件都完全是一样的。可以看到在这种情况下,增加一台服务器,我们需要做一件完全重复的事情。

本着不浪费时间做重复的工作的想法,小张想,要不然用 Ansible 来统一管理服务器操作和配置吧,但考虑到后续服务器上还需要部署其他的服务,常规的这样部署,容易干扰彼此的环境。

所以我们想到了用虚拟化的技术,但是根据一般的经验,类似 KVM 这样的虚拟化技术,可能在资源消耗上较多, 不够轻量级。而容器化相对来看,比较轻量级,也比较符合我们的预期,一次构建,随处执行。我们选择当前最热门的 Docker .

既然技术选型确定了,那很简单,在我们现在三台服务器上安装 Docker ,安装过程不再赘述,可以参考 Docker 的官方安装文档

此时,我们需要做的事情,也便只是将我们的服务构建成一个镜像,需要编写一个 Dockerfile,构建一个镜像并部署到每台服务器上便可。

聊了这么多,我们现在已经将我们的服务运行到了容器中,而此处的 Docker 便是我们选择的容器运行时。选择它的最主要原因,便是为了环境隔离和避免重复工作。

而 Docker 如果对应于 K8S 集群中的概念,便是 Container Runtime,这里还有其他的选择,比如 rkt,runc 和其他实现了 OCI 规范的运行时。

总结

在这节里面,我们了解到了 Node 其实就是用于工作的服务器,它有一些状态和信息,当这些条件都满足一些条件判断时,Node 便处于 Ready 状态,可用于执行后续的工作。

Deployment 可理解为一种对期望状态的描述, Pod 作为集群中可调度的最小单元,我们会在后面详细讲解其细节。

Docker 是我们选择的容器运行时,可运行我们构建的服务镜像,减少在环境方面所做的重复工作,并且也非常便于部署。除了 Docker 外还存在其他的容器运行时。

了解到这些基本概念后,下节我们从宏观的角度上来认识 K8S 的整体架构,以便我们后续的学习和实践。